<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="file" id="file" onchange="upload()">


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="spark-md5.js"></script>
<script>
    function upload() {
        let selector = document.querySelector("#file");
        let file = selector.files[0];// blob 二进制文件(File)对象
        let size = file.size;// 文件总大小
        let type = file.name.split(".")[1];
        console.log(file)
        md5(file).then(md5=>{
            console.log(md5)
            let len = isSecon(md5,type); //查询是否秒传  len 是指之前已上传完的内容
            if (len===-1){
                alert("秒传成功");
                return
            }
            // 计算 当前分片的大小
            let count = totalCount(size-len,1024*1024);
            const block_size = 1024*1024;// 每个分片的大小
            let start = len;
            let end;
            let status = 0;//status 上传状态,0: 正在继续分片上传,1 最后一片上传
            for (let i = 1; i <= count; i++) {
                end = start+block_size;
                if (end>size){
                    end = size;
                    status = 1;
                }
                // 返回切片的文件
                const blobFile = slicerFile(file,start,end);
                start = end;
                uploadFile(blobFile,i,md5,status,type)
            }
        });
    }

    /**
     * @return number 总的分片数量
     * @param size 总大小
     * @param Block_size 每一个分片的大小
     */
    function totalCount(size,Block_size) {
        return Math.ceil(size/Block_size)
    }

    /**
     * 文件切片
     * @param file
     * @param start 开始切片的位置
     * @param end   结束位置
     */
    function slicerFile(file,start,end) {
        return file.slice(start, end)
    }

    /**
     * 文件上传 方法
     * @param file
     * @param index 第几片
     * @param md5 md5值
     * @param status 状态
     * @param type 文件类型
     */
    function uploadFile(file,index,md5,status,type) {
        var fd = new FormData()
        fd.append('file', file)
        fd.append('index', index)
        fd.append('md5', md5)
        fd.append('status', status)
        fd.append('type', type)
        $.ajax({
            method: 'POST',
            url: '/upload',
            async:false,
            data: fd,
            // 不修改 Content-Type 属性，使用 FormData 默认的 Content-Type 值
            contentType: false,
            // 不对 FormData 中的数据进行 url 编码，而是将 FormData 数据原样发送到服务器
            processData: false,
            success: function(res) {
                console.log(res)
            }
        })

    }

    /**
     * 秒传查询
     * @param md5
     * @param type
     * @return {*}
     */
    function isSecon(md5,type) {
        let start;
        $.ajax({
            async:false,
            url: '/isSecon',
            data: {md5,type},
            success:function (res) {
                start = res.data;
            }
        })
        return start;
    }


    /**
     *  文件 md5 计算
     * @param file
     * @param chunkSize
     * @return {Promise<unknown>}
     */
    function md5(file, chunkSize=2097152) {
        return new Promise((resolve, reject) => {
            let blobSlice =
                File.prototype.slice ||
                File.prototype.mozSlice ||
                File.prototype.webkitSlice;

            let chunks = Math.ceil(file.size / chunkSize);
            let currentChunk = 0;
            let spark = new SparkMD5.ArrayBuffer(); //追加数组缓冲区。
            let fileReader = new FileReader(); //读取文件
            fileReader.onload = function (e) {
                spark.append(e.target.result);
                currentChunk++;
                if (currentChunk < chunks) {
                    loadNext();
                } else {
                    let md5 = spark.end(); //完成md5的计算，返回十六进制结果。
                    resolve(md5);
                    // console.log(md5);
                }
            };

            fileReader.onerror = function (e) {
                reject(e);
            };

            function loadNext() {
                let start = currentChunk * chunkSize;
                let end = start + chunkSize;
                if (end > file.size) {
                    end = file.size;
                }
                fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
            }

            loadNext();
        });
    }

</script>
</body>
</html>
